package ms.jasim.framework;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import ms.jasim.model.Actor;
import ms.jasim.model.Capability;
import ms.jasim.model.Evaluator;
import ms.jasim.model.Goal;
import ms.jasim.model.JasimTemplate;
import ms.jasim.model.ModelObject;
import ms.jasim.model.event.Event;
import ms.jasim.model.event.EventReaction;
import ms.jasim.model.items.PropertyDescriptor;
import ms.jasim.model.items.PropertyDescriptorList;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;

public class TemplateProvider implements ITemplateProvider, IDescriptorProvider {

	private IConfiguration config;
	private JasimTemplate model;

	public TemplateProvider(IConfiguration config) {
		this.config = config;
	}
	
	@Override
	public List<Evaluator> getEvaluatorTemplates() {
		ArrayList<Evaluator> evaluatorTemplates = null;
		
		JasimTemplate model = getTemplateModel();
		if (model != null) { 
			evaluatorTemplates = new ArrayList<Evaluator>(); 
			for (Evaluator eval: model.getEvaluators()) {
				eval.setLabel(eval.getName());
				Evaluator copy = (Evaluator) EcoreUtil.copy(eval);
				copy.setName("");
				setPredefined(copy);
				copy.setPredefined(false);
				evaluatorTemplates.add(copy);
			}
		}
		return evaluatorTemplates;
	}
	
	@Override
	public List<Event> getEventTemplates() {
		ArrayList<Event> events = null;
		JasimTemplate template = getTemplateModel();
		if (template != null) {
			events = new ArrayList<Event>();
			for (Event ev: template.getEventTemplate().getEvent()) {
				ev.setLabel(ev.getName());
				Event copy = (Event) EcoreUtil.copy(ev);
				copy.setName("");
				setPredefined(copy);
				copy.setPredefined(false);
				events.add(copy);
			}
		}
		return events;
	}

	@Override
	public List<EventReaction> getCustomReactionTemplates() {
		ArrayList<EventReaction> reactions = null;
		JasimTemplate template = getTemplateModel();
		if (template != null) {
			reactions = new ArrayList<EventReaction>();
			for (EventReaction act: template.getCustomReactions().getReaction()) {
				EventReaction copy = (EventReaction) EcoreUtil.copy(act);
				setPredefined(copy);
				copy.setPredefined(false);
				reactions.add(copy);
			}
		}
		return reactions;
	}
	
	private JasimTemplate getTemplateModel() {
		if (this.model == null) {
			String filename = config.getString("template", null);
			if (filename != null && new File(filename).exists()) {
				ResourceSet set= new ResourceSetImpl();
				Resource resource= set.getResource(URI.createFileURI(filename), true);
				EObject rootObj = resource.getContents().get(0);
				this.model = (JasimTemplate) (rootObj instanceof JasimTemplate? rootObj : null);
			}
		}
		return this.model;
	}
	
	public static void setPredefined(ModelObject obj) {
		obj.setPredefined(true);
		for(TreeIterator<EObject> iterator = obj.eAllContents(); iterator.hasNext();) {
			ModelObject subObj = (ModelObject) iterator.next();
			setPredefined(subObj);
		}
		
	}

	
	@Override
	public List<PropertyDescriptor> getPropertyDescriptors(Class<?> clazz) {
		PropertyDescriptorList list = getPropertyDescriptorList(clazz);
		return list != null ? list.getPropertyDescriptor() : null;
	}
	
	@Override
	public PropertyDescriptorList getPropertyDescriptorList(Class<?> clazz) {
		JasimTemplate template = getTemplateModel();
		if (template != null) 
			if (Actor.class.isAssignableFrom(clazz))
				return template.getActorDescriptors();
			else if (Goal.class.isAssignableFrom(clazz))
				return template.getGoalDescriptors();
			else if (Capability.class.isAssignableFrom(clazz))
				return template.getCapabilityDescriptors();
		return null;
	}
}
